home *** CD-ROM | disk | FTP | other *** search
/ Delphi Developer's Kit 1996 / Delphi Developer's Kit 1996.iso / power / wfc007.000 / src / registry.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-22  |  27.5 KB  |  1,149 lines

  1. #include <wfc.h>
  2. #pragma hdrstop
  3.  
  4. /*
  5. ** Author: Samuel R. Blackburn
  6. ** CI$: 76300,326
  7. ** Internet: sammy@sed.csc.com
  8. **
  9. ** You can use it any way you like.
  10. */
  11.  
  12. #if defined( _DEBUG )
  13. #undef THIS_FILE
  14. static char BASED_CODE THIS_FILE[] = __FILE__;
  15. #endif
  16.  
  17. IMPLEMENT_DYNAMIC( CRegistry, CObject );
  18.  
  19. HKEY CRegistry::keyLocalMachine = HKEY_LOCAL_MACHINE;
  20. HKEY CRegistry::keyClassesRoot  = HKEY_CLASSES_ROOT;
  21. HKEY CRegistry::keyUsers        = HKEY_USERS;
  22. HKEY CRegistry::keyCurrentUser  = HKEY_CURRENT_USER;
  23.  
  24. CRegistry::CRegistry()
  25. {
  26.    m_Initialize();
  27. }
  28.  
  29. CRegistry::~CRegistry()
  30. {
  31.    if ( m_RegistryHandle != (HKEY) NULL )
  32.    {
  33.       Close();
  34.    }
  35.  
  36.    m_Initialize();
  37. }
  38.  
  39. void CRegistry::m_Initialize( void )
  40. {
  41.    ASSERT_VALID( this );
  42.  
  43.    /*
  44.    ** Make sure everything is zeroed out
  45.    */
  46.  
  47.    ClassName.Empty();
  48.    ComputerName.Empty();
  49.    KeyName.Empty();
  50.    RegistryName.Empty();
  51.  
  52.    m_KeyHandle                    = (HKEY) NULL;
  53.    m_ErrorCode                    = 0L;
  54.    NumberOfSubkeys                = 0;
  55.    m_LongestSubkeyNameLength      = 0;
  56.    m_LongestClassNameLength       = 0;
  57.    NumberOfValues                 = 0;
  58.    m_LongestValueNameLength       = 0;
  59.    m_LongestValueDataLength       = 0;
  60.    m_SecurityDescriptorLength     = 0;
  61.    m_LastWriteTime.dwLowDateTime  = 0;
  62.    m_LastWriteTime.dwHighDateTime = 0;
  63. }
  64.  
  65. BOOL CRegistry::Close( void )
  66. {
  67.    ASSERT_VALID( this );
  68.  
  69.    if ( m_RegistryHandle == (HKEY) NULL )
  70.    {
  71.       return( TRUE );
  72.    }
  73.  
  74.    m_ErrorCode = ::RegCloseKey( m_RegistryHandle );
  75.  
  76.    if ( m_ErrorCode == ERROR_SUCCESS )
  77.    {
  78.       m_RegistryHandle = (HKEY) NULL;
  79.       m_Initialize();
  80.  
  81.       return( TRUE );
  82.    }
  83.    else
  84.    {
  85.       return( FALSE );
  86.    }
  87. }
  88.  
  89. BOOL CRegistry::Connect( HKEY key_to_open, LPCTSTR name_of_computer )
  90. {
  91.    ASSERT_VALID( this );
  92.  
  93.    /*
  94.    ** name_of_computer can be NULL
  95.    */
  96.  
  97.    if ( key_to_open == keyClassesRoot || key_to_open == keyCurrentUser )
  98.    {
  99.       if ( name_of_computer == NULL )
  100.       {
  101.          /*
  102.          ** NT won't allow you to connect to these hives via RegConnectRegistry so we'll just skip that step
  103.          */
  104.  
  105.          m_RegistryHandle = key_to_open;
  106.          m_ErrorCode      = ERROR_SUCCESS;
  107.       }
  108.       else
  109.       {
  110.          m_ErrorCode = ERROR_INVALID_HANDLE;
  111.       }
  112.    }
  113.    else
  114.    {
  115.       m_ErrorCode = ::RegConnectRegistry( (char *) name_of_computer, key_to_open, &m_RegistryHandle );
  116.    }
  117.  
  118.    if ( m_ErrorCode == ERROR_SUCCESS )
  119.    {
  120.       if ( name_of_computer == NULL )
  121.       {
  122.          TCHAR computer_name[ MAX_PATH ] = "";
  123.          DWORD size = MAX_PATH;
  124.  
  125.          if ( ::GetComputerName( computer_name, &size ) == TRUE )
  126.          {
  127.             ComputerName = computer_name;
  128.          }
  129.          else
  130.          {
  131.             ComputerName.Empty();
  132.          }
  133.       }
  134.       else
  135.       {
  136.          ComputerName = name_of_computer;
  137.       }
  138.  
  139.       /*
  140.       ** It would be nice to use a switch statement here but I get a "not integral" error!
  141.       */
  142.  
  143.       if ( key_to_open == HKEY_LOCAL_MACHINE )
  144.       {
  145.          RegistryName = "HKEY_LOCAL_MACHINE";
  146.       }
  147.       else if ( key_to_open == HKEY_CLASSES_ROOT )
  148.       {
  149.          RegistryName = "HKEY_CLASSES_ROOT";
  150.       }
  151.       else if ( key_to_open == HKEY_USERS )
  152.       {
  153.          RegistryName = "HKEY_USERS";
  154.       }
  155.       else if ( key_to_open == HKEY_CURRENT_USER )
  156.       {
  157.          RegistryName = "HKEY_CURRENT_USER";
  158.       }
  159.       else
  160.       {
  161.          RegistryName = "Unknown";
  162.       }
  163.  
  164.       return( TRUE );
  165.    }
  166.    else
  167.    {
  168.       return( FALSE );
  169.    }
  170. }
  171.  
  172. BOOL CRegistry::Create( LPCTSTR               name_of_subkey, 
  173.                         LPCTSTR               name_of_class,
  174.                         CreateOptions         options, 
  175.                         CreatePermissions     permissions, 
  176.                         LPSECURITY_ATTRIBUTES security_attributes_p,
  177.                         CreationDisposition * disposition_p )
  178. {
  179.    ASSERT_VALID( this );
  180.    ASSERT( name_of_subkey != NULL );
  181.  
  182.    if ( name_of_subkey == NULL )
  183.    {
  184.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  185.       return( FALSE );
  186.    }
  187.  
  188.    DWORD disposition = 0;
  189.  
  190.    if ( name_of_class == NULL )
  191.    {
  192.       name_of_class = "";
  193.    }
  194.  
  195.    m_ErrorCode = ::RegCreateKeyEx( m_RegistryHandle,
  196.                                    name_of_subkey,
  197.                            (DWORD) 0,
  198.                           (char *) name_of_class,
  199.                                    options,
  200.                                    permissions,
  201.                                    security_attributes_p,
  202.                                   &m_KeyHandle,
  203.                                   &disposition );
  204.  
  205.    if ( m_ErrorCode == ERROR_SUCCESS )
  206.    {
  207.       if ( disposition_p != NULL )
  208.       {
  209.          *disposition_p = (CreationDisposition) disposition;
  210.       }
  211.  
  212.       KeyName = name_of_subkey;
  213.  
  214.       return( TRUE );
  215.    }
  216.    else
  217.    {
  218.       return( FALSE );
  219.    }
  220. }
  221.  
  222. BOOL CRegistry::DeleteKey( LPCTSTR name_of_key_to_delete )
  223. {
  224.    ASSERT_VALID( this );
  225.    ASSERT( name_of_key_to_delete != NULL );
  226.  
  227.    if ( name_of_key_to_delete == NULL )
  228.    {
  229.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  230.       return( FALSE );
  231.    }
  232.  
  233.    /*
  234.    ** You can't delete a key given a full path. What you have to do is back up one level and then do a delete
  235.    */
  236.  
  237.    CString full_key_name = name_of_key_to_delete;
  238.  
  239.    if ( full_key_name.Find( '\\' ) == (-1) )
  240.    {
  241.       /*
  242.       ** User had not given us a full path so assume the name of the key he passed us
  243.       ** is a key off of the current key
  244.       */
  245.  
  246.       m_ErrorCode = ::RegDeleteKey( m_KeyHandle, name_of_key_to_delete );
  247.    }
  248.    else
  249.    {
  250.       int last_back_slash_location = full_key_name.GetLength() - 1;
  251.  
  252.       /*
  253.       ** We know this loop will succeed because a back slash was found in the above if statement
  254.       */
  255.  
  256.       while( full_key_name[ last_back_slash_location ] != '\\' )
  257.       {
  258.          last_back_slash_location--;
  259.       }
  260.  
  261.       CString currently_opened_key_name = KeyName;
  262.  
  263.       CString parent_key_name = full_key_name.Left( last_back_slash_location );
  264.       CString child_key_name  = full_key_name.Right( ( full_key_name.GetLength() - last_back_slash_location ) - 1 );
  265.  
  266.       /*
  267.       ** Now we open the parent key and delete the child
  268.       */
  269.  
  270.       if ( Open( parent_key_name ) == TRUE )
  271.       {
  272.          m_ErrorCode = ::RegDeleteKey( m_KeyHandle, child_key_name );
  273.       }
  274.       else
  275.       {
  276.          KeyName = currently_opened_key_name;
  277.          return( FALSE );
  278.       }
  279.    }
  280.  
  281.    if ( m_ErrorCode == ERROR_SUCCESS )
  282.    {
  283.       return( TRUE );
  284.    }
  285.    else
  286.    {
  287.       return( FALSE );
  288.    }
  289. }                  
  290.  
  291. BOOL CRegistry::DeleteValue( LPCTSTR name_of_value_to_delete )
  292. {
  293.    ASSERT_VALID( this );
  294.  
  295.    /*
  296.    ** name_of_value_to_delete can be NULL
  297.    */
  298.  
  299.    m_ErrorCode = ::RegDeleteValue( m_KeyHandle, (LPTSTR) name_of_value_to_delete );
  300.  
  301.    if ( m_ErrorCode == ERROR_SUCCESS )
  302.    {
  303.       return( TRUE );
  304.    }
  305.    else
  306.    {
  307.       return( FALSE );
  308.    }
  309. }
  310.  
  311. BOOL CRegistry::EnumerateKeys( const DWORD subkey_index, CString& subkey_name, CString& class_name )
  312. {
  313.    ASSERT_VALID( this );
  314.  
  315.    TCHAR subkey_name_string[ 2048 ];
  316.    TCHAR class_name_string[ 2048 ];
  317.  
  318.    DWORD size_of_subkey_name_string = sizeof( subkey_name_string ) - 1;
  319.    DWORD size_of_class_name_string  = sizeof( class_name_string  ) - 1;
  320.  
  321.    ::ZeroMemory( subkey_name_string, sizeof( subkey_name_string ) );
  322.    ::ZeroMemory( class_name_string,  sizeof( class_name_string  ) );
  323.  
  324.    m_ErrorCode = ::RegEnumKeyEx( m_KeyHandle, 
  325.                                  subkey_index, 
  326.                                  subkey_name_string, 
  327.                                 &size_of_subkey_name_string,
  328.                                  NULL,
  329.                                  class_name_string,
  330.                                 &size_of_class_name_string,
  331.                                 &m_LastWriteTime );
  332.  
  333.    if ( m_ErrorCode == ERROR_SUCCESS )
  334.    {
  335.       subkey_name = subkey_name_string;
  336.       class_name  = class_name_string;
  337.  
  338.       return( TRUE );
  339.    }
  340.    else
  341.    {
  342.       return( FALSE );
  343.    }
  344. }
  345.  
  346. BOOL CRegistry::EnumerateValues( const DWORD    value_index, 
  347.                                  CString&       name_of_value, 
  348.                                  KeyValueTypes& type_code,
  349.                                  LPBYTE         data_buffer,
  350.                                  DWORD&         size_of_data_buffer )
  351. {
  352.    ASSERT_VALID( this );
  353.  
  354.    /*
  355.    ** data_buffer and size_of_data_buffer can be NULL
  356.    */
  357.  
  358.    DWORD temp_type_code = type_code;
  359.  
  360.    TCHAR temp_name[ 2048 ];
  361.  
  362.    ::ZeroMemory( temp_name, sizeof( temp_name ) );
  363.  
  364.    DWORD temp_name_size = sizeof( temp_name );
  365.    
  366.    m_ErrorCode = ::RegEnumValue( m_KeyHandle,
  367.                                  value_index,
  368.                                  temp_name,
  369.                                 &temp_name_size,
  370.                                  NULL,
  371.                                 &temp_type_code,
  372.                                  data_buffer,
  373.                                 &size_of_data_buffer );
  374.  
  375.    if ( m_ErrorCode == ERROR_SUCCESS )
  376.    {
  377.       type_code     = (KeyValueTypes) temp_type_code;
  378.       name_of_value = temp_name;
  379.  
  380.       return( TRUE );
  381.    }
  382.    else
  383.    {
  384.       return( FALSE );
  385.    }
  386. }
  387.  
  388. BOOL CRegistry::Flush( void )
  389. {
  390.    ASSERT_VALID( this );
  391.  
  392.    m_ErrorCode = ::RegFlushKey( m_KeyHandle );
  393.  
  394.    if ( m_ErrorCode == ERROR_SUCCESS )
  395.    {
  396.       return( TRUE );
  397.    }
  398.    else
  399.    {
  400.       return( FALSE );
  401.    }
  402. }
  403.  
  404. BOOL CRegistry::GetBinaryValue( LPCTSTR name_of_value, CByteArray& return_array )
  405. {
  406.    ASSERT_VALID( this );
  407.    ASSERT( name_of_value != NULL );
  408.  
  409.    if ( name_of_value == NULL )
  410.    {
  411.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  412.       return( FALSE );
  413.    }
  414.  
  415.    DWORD size_of_buffer = m_LongestValueDataLength;
  416.  
  417.    LPBYTE memory_buffer = (LPBYTE) ::malloc( size_of_buffer );
  418.  
  419.    if ( memory_buffer == NULL )
  420.    {
  421.       m_ErrorCode = ::GetLastError();
  422.       return( FALSE );
  423.    }
  424.  
  425.    BOOL return_value = TRUE;
  426.  
  427.    KeyValueTypes type = typeBinary;
  428.  
  429.    if ( QueryValue( name_of_value, type, memory_buffer, size_of_buffer ) == TRUE )
  430.    {
  431.       /*
  432.       ** We've got data so give it back to the caller
  433.       */
  434.  
  435.       return_array.RemoveAll();
  436.  
  437.       DWORD index = 0;
  438.  
  439.       while( index < size_of_buffer )
  440.       {
  441.          return_array.Add( memory_buffer[ index ] );
  442.          index++;
  443.       }
  444.  
  445.       return_value = TRUE;
  446.    }
  447.    else
  448.    {
  449.       return_value = FALSE;
  450.    }
  451.  
  452.    ::free( memory_buffer );
  453.  
  454.    return( return_value );
  455. }
  456.  
  457. BOOL CRegistry::GetDoubleWordValue( LPCTSTR name_of_value, DWORD& return_value )
  458. {
  459.    ASSERT_VALID( this );
  460.    ASSERT( name_of_value != NULL );
  461.  
  462.    if ( name_of_value == NULL )
  463.    {
  464.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  465.       return( FALSE );
  466.    }
  467.  
  468.    DWORD size_of_buffer = sizeof( DWORD );
  469.  
  470.    KeyValueTypes type = typeDoubleWord;
  471.  
  472.    return( QueryValue( name_of_value, type, (LPBYTE) &return_value, size_of_buffer ) );
  473. }
  474.  
  475. BOOL CRegistry::GetErrorCode( void ) const
  476. {
  477.    ASSERT_VALID( this );
  478.    return( m_ErrorCode );
  479. }
  480.  
  481. BOOL CRegistry::GetSecurity( const SECURITY_INFORMATION what_you_want_to_know,
  482.                              PSECURITY_DESCRIPTOR       data_buffer,
  483.                              DWORD&                     size_of_data_buffer )
  484. {
  485.    ASSERT_VALID( this );
  486.    ASSERT( data_buffer != NULL );
  487.  
  488.    if ( data_buffer == NULL )
  489.    {
  490.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  491.       return( FALSE );
  492.    }
  493.  
  494.    m_ErrorCode = ::RegGetKeySecurity( m_KeyHandle,
  495.                                       what_you_want_to_know,
  496.                                       data_buffer,
  497.                                      &size_of_data_buffer );
  498.  
  499.    if ( m_ErrorCode == ERROR_SUCCESS )
  500.    {
  501.       return( TRUE );
  502.    }
  503.    else
  504.    {
  505.       return( FALSE );
  506.    }
  507. }
  508.  
  509. BOOL CRegistry::GetStringValue( LPCTSTR name_of_value, CString& return_string )
  510. {
  511.    ASSERT_VALID( this );
  512.    ASSERT( name_of_value != NULL );
  513.  
  514.    if ( name_of_value == NULL )
  515.    {
  516.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  517.       return( FALSE );
  518.    }
  519.  
  520.    TCHAR temp_string[ 2048 ];
  521.    DWORD size_of_buffer = 2048;
  522.  
  523.    ::ZeroMemory( temp_string, sizeof( temp_string ) );
  524.  
  525.    KeyValueTypes type = typeString;
  526.  
  527.    if ( QueryValue( name_of_value, type, (LPBYTE) temp_string, size_of_buffer ) == TRUE )
  528.    {
  529.       return_string = temp_string;
  530.       return( TRUE );
  531.    }
  532.    else
  533.    {
  534.       return_string.Empty();
  535.       return( FALSE );
  536.    }
  537. }
  538.  
  539. BOOL CRegistry::GetStringArrayValue( LPCTSTR name_of_value, CStringArray& return_array )
  540. {
  541.    ASSERT_VALID( this );
  542.    ASSERT( name_of_value != NULL );
  543.  
  544.    if ( name_of_value == NULL )
  545.    {
  546.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  547.       return( FALSE );
  548.    }
  549.  
  550.    DWORD size_of_buffer = m_LongestValueDataLength;
  551.  
  552.    LPBYTE memory_buffer = (LPBYTE) ::malloc( size_of_buffer );
  553.  
  554.    if ( memory_buffer == NULL )
  555.    {
  556.       m_ErrorCode = ::GetLastError();
  557.       return( FALSE );
  558.    }
  559.  
  560.    BOOL return_value = TRUE;
  561.  
  562.    KeyValueTypes type = typeMultipleString; // A double NULL terminated string
  563.  
  564.    if ( QueryValue( name_of_value, type, memory_buffer, size_of_buffer ) == TRUE )
  565.    {
  566.       /*
  567.       ** We've got data so give it back to the caller
  568.       */
  569.  
  570.       LPTSTR strings = (LPTSTR) memory_buffer;
  571.  
  572.       return_array.RemoveAll();
  573.  
  574.       while( strings[ 0 ] != 0x00 )
  575.       {
  576.          return_array.Add( (LPCTSTR) strings );
  577.          strings += ( ::strlen( (LPCTSTR) strings ) + 1 );
  578.       }
  579.  
  580.       return_value = TRUE;
  581.    }
  582.    else
  583.    {
  584.       return_value = FALSE;
  585.    }
  586.  
  587.    ::free( memory_buffer );
  588.  
  589.    return( return_value );
  590. }
  591.  
  592. BOOL CRegistry::GetValue( LPCTSTR name_of_value, CByteArray& return_array )
  593. {
  594.    ASSERT_VALID( this );
  595.    ASSERT( name_of_value != NULL );
  596.  
  597.    if ( name_of_value == NULL )
  598.    {
  599.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  600.       return( FALSE );
  601.    }
  602.  
  603.    return( GetBinaryValue( name_of_value, return_array ) );
  604. }
  605.  
  606. BOOL CRegistry::GetValue( LPCTSTR name_of_value, DWORD& return_value )
  607. {
  608.    ASSERT_VALID( this );
  609.    ASSERT( name_of_value != NULL );
  610.  
  611.    if ( name_of_value == NULL )
  612.    {
  613.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  614.       return( FALSE );
  615.    }
  616.  
  617.    return( GetDoubleWordValue( name_of_value, return_value ) );
  618. }
  619.  
  620. BOOL CRegistry::GetValue( LPCTSTR name_of_value, CString& return_string )
  621. {
  622.    ASSERT_VALID( this );
  623.    ASSERT( name_of_value != NULL );
  624.  
  625.    if ( name_of_value == NULL )
  626.    {
  627.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  628.       return( FALSE );
  629.    }
  630.  
  631.    return( GetStringValue( name_of_value, return_string ) );
  632. }
  633.  
  634. BOOL CRegistry::GetValue( LPCTSTR name_of_value, CStringArray& return_array )
  635. {
  636.    ASSERT_VALID( this );
  637.    ASSERT( name_of_value != NULL );
  638.  
  639.    if ( name_of_value == NULL )
  640.    {
  641.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  642.       return( FALSE );
  643.    }
  644.  
  645.    return( GetStringArrayValue( name_of_value, return_array ) );
  646. }
  647.  
  648. BOOL CRegistry::Load( LPCTSTR name_of_subkey, LPCTSTR name_of_file_containing_information )
  649. {
  650.    ASSERT_VALID( this );
  651.    ASSERT( name_of_subkey != NULL );
  652.    ASSERT( name_of_file_containing_information != NULL );
  653.  
  654.    if ( name_of_subkey == NULL || name_of_file_containing_information == NULL )
  655.    {
  656.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  657.       return( FALSE );
  658.    }
  659.  
  660.    m_ErrorCode = ::RegLoadKey( m_RegistryHandle, name_of_subkey, name_of_file_containing_information );
  661.  
  662.    if ( m_ErrorCode == ERROR_SUCCESS )
  663.    {
  664.       return( TRUE );
  665.    }
  666.    else
  667.    {
  668.       return( FALSE );
  669.    }
  670. }
  671.  
  672. BOOL CRegistry::NotifyChange( const HANDLE             event_handle, 
  673.                               const NotifyChangeFilter changes_to_be_reported,
  674.                               const BOOL               this_subkey_or_all_subkeys,
  675.                               const BOOL               wait_for_change_or_signal_event )
  676. {
  677.    ASSERT_VALID( this );
  678.  
  679.    m_ErrorCode = ::RegNotifyChangeKeyValue( m_KeyHandle,
  680.                                             this_subkey_or_all_subkeys,
  681.                                             changes_to_be_reported,
  682.                                             event_handle,
  683.                                             wait_for_change_or_signal_event );
  684.  
  685.    if ( m_ErrorCode == ERROR_SUCCESS )
  686.    {
  687.       return( TRUE );
  688.    }
  689.    else
  690.    {
  691.       return( FALSE );
  692.    }
  693. }
  694.  
  695. BOOL CRegistry::Open( LPCTSTR name_of_subkey_to_open, const CreatePermissions security_access_mask )
  696. {
  697.    ASSERT_VALID( this );
  698.  
  699.    /*
  700.    ** name_of_subkey_to_open can be NULL
  701.    */
  702.  
  703.    m_ErrorCode = ::RegOpenKeyEx( m_RegistryHandle, name_of_subkey_to_open, NULL, security_access_mask, &m_KeyHandle );
  704.  
  705.    if ( m_ErrorCode == ERROR_SUCCESS )
  706.    {
  707.       QueryInfo();
  708.       KeyName = name_of_subkey_to_open;
  709.  
  710.       return( TRUE );
  711.    }
  712.    else
  713.    {
  714.       return( FALSE );
  715.    }
  716. }
  717.  
  718. BOOL CRegistry::QueryInfo( void )
  719. {
  720.    ASSERT_VALID( this );
  721.  
  722.    TCHAR class_name[ 2048 ];
  723.  
  724.    DWORD size_of_class_name = sizeof( class_name ) - 1;
  725.  
  726.    ::ZeroMemory( class_name, sizeof( class_name ) );
  727.  
  728.    m_ErrorCode = ::RegQueryInfoKey( m_KeyHandle,
  729.                                     class_name,
  730.                                    &size_of_class_name,
  731.                           (LPDWORD) NULL,
  732.                                    &NumberOfSubkeys,
  733.                                    &m_LongestSubkeyNameLength,
  734.                                    &m_LongestClassNameLength,
  735.                                    &NumberOfValues,
  736.                                    &m_LongestValueNameLength,
  737.                                    &m_LongestValueDataLength,
  738.                                    &m_SecurityDescriptorLength,
  739.                                    &m_LastWriteTime );
  740.  
  741.    if ( m_ErrorCode == ERROR_SUCCESS )
  742.    {
  743.       ClassName = class_name;
  744.       LastWriteTime = CTime( m_LastWriteTime );
  745.  
  746.       return( TRUE );
  747.    }
  748.    else
  749.    {
  750.       return( FALSE );
  751.    }
  752. }
  753.  
  754. BOOL CRegistry::QueryValue( LPCTSTR        name_of_value, 
  755.                             KeyValueTypes& value_type, 
  756.                             LPBYTE         address_of_buffer, 
  757.                             DWORD&         size_of_buffer )
  758. {
  759.    ASSERT_VALID( this );
  760.    ASSERT( name_of_value != NULL );
  761.  
  762.    /*
  763.    ** address_of_buffer and size_of_buffer can be NULL
  764.    */
  765.  
  766.    if ( name_of_value == NULL )
  767.    {
  768.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  769.       return( FALSE );
  770.    }
  771.  
  772.    DWORD temp_data_type = (DWORD) value_type;
  773.  
  774.    m_ErrorCode = ::RegQueryValueEx( m_KeyHandle,
  775.                            (char *) name_of_value,
  776.                                     NULL,
  777.                                    &temp_data_type,
  778.                                     address_of_buffer,
  779.                                    &size_of_buffer );
  780.  
  781.    if ( m_ErrorCode == ERROR_SUCCESS )
  782.    {
  783.       value_type = (KeyValueTypes) temp_data_type;
  784.       return( TRUE );
  785.    }
  786.    else
  787.    {
  788.       return( FALSE );
  789.    }
  790. }
  791.  
  792. BOOL CRegistry::Replace( LPCTSTR name_of_subkey,
  793.                          LPCTSTR name_of_file_with_new_data,
  794.                          LPCTSTR name_of_backup_file )
  795. {
  796.    ASSERT_VALID( this );
  797.    ASSERT( name_of_subkey             != NULL );
  798.    ASSERT( name_of_file_with_new_data != NULL );
  799.    ASSERT( name_of_backup_file        != NULL );
  800.  
  801.    if ( name_of_subkey             == NULL ||
  802.         name_of_file_with_new_data == NULL ||
  803.         name_of_backup_file        == NULL )
  804.    {
  805.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  806.       return( FALSE );
  807.    }
  808.  
  809.    m_ErrorCode = ::RegReplaceKey( m_KeyHandle, 
  810.                                   name_of_subkey,
  811.                                   name_of_file_with_new_data,
  812.                                   name_of_backup_file );
  813.  
  814.    if ( m_ErrorCode == ERROR_SUCCESS )
  815.    {
  816.       return( TRUE );
  817.    }
  818.    else
  819.    {
  820.       return( FALSE );
  821.    }
  822. }
  823.  
  824. BOOL CRegistry::Restore( LPCTSTR name_of_file_holding_saved_tree, const DWORD volatility_flags )
  825. {
  826.    ASSERT_VALID( this );
  827.    ASSERT( name_of_file_holding_saved_tree != NULL );
  828.  
  829.    if ( name_of_file_holding_saved_tree == NULL )
  830.    {
  831.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  832.       return( FALSE );
  833.    }
  834.  
  835.    m_ErrorCode = ::RegRestoreKey( m_KeyHandle,
  836.                                   name_of_file_holding_saved_tree,
  837.                                   volatility_flags );
  838.  
  839.    if ( m_ErrorCode == ERROR_SUCCESS )
  840.    {
  841.       return( TRUE );
  842.    }
  843.    else
  844.    {
  845.       return( FALSE );
  846.    }
  847. }
  848.  
  849. BOOL CRegistry::Save( LPCTSTR name_of_file_to_hold_tree, LPSECURITY_ATTRIBUTES security_attributes_p )
  850. {
  851.    ASSERT_VALID( this );
  852.    ASSERT( name_of_file_to_hold_tree != NULL );
  853.  
  854.    if ( name_of_file_to_hold_tree == NULL )
  855.    {
  856.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  857.       return( FALSE );
  858.    }
  859.  
  860.    m_ErrorCode = ::RegSaveKey( m_KeyHandle, name_of_file_to_hold_tree, security_attributes_p );
  861.  
  862.    if ( m_ErrorCode == ERROR_SUCCESS )
  863.    {
  864.       return( TRUE );
  865.    }
  866.    else
  867.    {
  868.       return( FALSE );
  869.    }
  870. }
  871.  
  872. BOOL CRegistry::SetBinaryValue( LPCTSTR name_of_value, const CByteArray& bytes_to_write )
  873. {
  874.    ASSERT_VALID( this );
  875.    ASSERT( name_of_value != NULL );
  876.  
  877.    if ( name_of_value == NULL )
  878.    {
  879.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  880.       return( FALSE );
  881.    }
  882.  
  883.    DWORD size_of_buffer = bytes_to_write.GetSize();
  884.  
  885.    LPBYTE memory_buffer = (LPBYTE) ::malloc( size_of_buffer );
  886.  
  887.    if ( memory_buffer == NULL )
  888.    {
  889.       m_ErrorCode = ::GetLastError();
  890.       return( FALSE );
  891.    }
  892.  
  893.    DWORD index = 0;
  894.  
  895.    while( index < size_of_buffer )
  896.    {
  897.       memory_buffer[ index ] = bytes_to_write[ index ];
  898.       index++;
  899.    }
  900.  
  901.    BOOL return_value = SetValue( name_of_value, typeBinary, memory_buffer, size_of_buffer );
  902.  
  903.    ::free( memory_buffer );
  904.  
  905.    return( return_value );
  906. }
  907.  
  908. BOOL CRegistry::SetDoubleWordValue( LPCTSTR name_of_value, DWORD value_to_write )
  909. {
  910.    ASSERT_VALID( this );
  911.    ASSERT( name_of_value != NULL );
  912.  
  913.    if ( name_of_value == NULL )
  914.    {
  915.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  916.       return( FALSE );
  917.    }
  918.  
  919.    return( SetValue( name_of_value, typeDoubleWord, (const PBYTE) &value_to_write, sizeof( DWORD ) ) );
  920. }
  921.  
  922. BOOL CRegistry::SetSecurity( const SECURITY_INFORMATION& security_information,
  923.                              const PSECURITY_DESCRIPTOR  security_descriptor_p )
  924. {
  925.    ASSERT_VALID( this );
  926.    ASSERT( security_descriptor_p != NULL );
  927.  
  928.    if ( security_descriptor_p == NULL )
  929.    {
  930.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  931.       return( FALSE );
  932.    }
  933.  
  934.    m_ErrorCode = ::RegSetKeySecurity( m_KeyHandle, security_information, security_descriptor_p );
  935.  
  936.    if ( m_ErrorCode == ERROR_SUCCESS )
  937.    {
  938.       return( TRUE );
  939.    }
  940.    else
  941.    {
  942.       return( FALSE );
  943.    }
  944. }
  945.  
  946. BOOL CRegistry::SetStringValue( LPCTSTR name_of_value, const CString& string_value )
  947. {
  948.    ASSERT_VALID( this );
  949.    ASSERT( name_of_value != NULL );
  950.  
  951.    if ( name_of_value == NULL )
  952.    {
  953.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  954.       return( FALSE );
  955.    }
  956.  
  957.    return( SetValue( name_of_value, typeString, (const PBYTE) (const char *) string_value, string_value.GetLength() + 1 ) );
  958. }
  959.  
  960. BOOL CRegistry::SetStringArrayValue( LPCTSTR name_of_value, const CStringArray& string_array )
  961. {
  962.    ASSERT_VALID( this );
  963.    ASSERT( name_of_value != NULL );
  964.  
  965.    if ( name_of_value == NULL )
  966.    {
  967.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  968.       return( FALSE );
  969.    }
  970.  
  971.    DWORD size_of_buffer = 0;
  972.  
  973.    /*
  974.    ** Find out how big our buffer needs to be...
  975.    */
  976.  
  977.    int index             = 0;
  978.    int number_of_strings = string_array.GetSize();
  979.  
  980.    CString temp_string;
  981.  
  982.    while( index < number_of_strings )
  983.    {
  984.       temp_string = string_array[ index ];
  985.       size_of_buffer += temp_string.GetLength() + 1;
  986.       index++;
  987.    }
  988.  
  989.    /*
  990.    ** Don't forget the second NULL needed for double null terminated strings...
  991.    */
  992.  
  993.    size_of_buffer++;
  994.  
  995.    LPBYTE memory_buffer = (LPBYTE) ::malloc( size_of_buffer );
  996.  
  997.    if ( memory_buffer == NULL )
  998.    {
  999.       m_ErrorCode = ::GetLastError();
  1000.       return( FALSE );
  1001.    }
  1002.  
  1003.    ::ZeroMemory( memory_buffer, size_of_buffer );
  1004.  
  1005.    /*
  1006.    ** OK, now add the strings to the memory buffer
  1007.    */
  1008.  
  1009.    LPTSTR string = (LPTSTR) memory_buffer;
  1010.  
  1011.    index             = 0;
  1012.    int string_length = 0;
  1013.  
  1014.    while( index < number_of_strings )
  1015.    {
  1016.       temp_string = string_array[ index ];
  1017.       ::strcpy( &string[ string_length ], temp_string );
  1018.       string_length += temp_string.GetLength() + 1;
  1019.  
  1020.       index++;
  1021.    }
  1022.  
  1023.    string_length++;
  1024.  
  1025.    BOOL return_value = TRUE;
  1026.  
  1027.    KeyValueTypes type = typeMultipleString; // A double NULL terminated string
  1028.  
  1029.    if ( SetValue( name_of_value, type, memory_buffer, size_of_buffer ) != TRUE )
  1030.    {
  1031.       return_value = FALSE;
  1032.    }
  1033.  
  1034.    ::free( memory_buffer );
  1035.  
  1036.    return( return_value );
  1037. }
  1038.  
  1039. BOOL CRegistry::SetValue( LPCTSTR name_of_value, const CByteArray& bytes_to_write )
  1040. {
  1041.    ASSERT_VALID( this );
  1042.    ASSERT( name_of_value != NULL );
  1043.  
  1044.    if ( name_of_value == NULL )
  1045.    {
  1046.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  1047.       return( FALSE );
  1048.    }
  1049.  
  1050.    return( SetBinaryValue( name_of_value, bytes_to_write ) );
  1051. }
  1052.  
  1053. BOOL CRegistry::SetValue( LPCTSTR name_of_value, DWORD value )
  1054. {
  1055.    ASSERT_VALID( this );
  1056.    ASSERT( name_of_value != NULL );
  1057.  
  1058.    if ( name_of_value == NULL )
  1059.    {
  1060.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  1061.       return( FALSE );
  1062.    }
  1063.  
  1064.    return( SetDoubleWordValue( name_of_value, value ) );
  1065. }
  1066.  
  1067. BOOL CRegistry::SetValue( LPCTSTR name_of_value, const CStringArray& strings_to_write )
  1068. {
  1069.    ASSERT_VALID( this );
  1070.    ASSERT( name_of_value != NULL );
  1071.  
  1072.    if ( name_of_value == NULL )
  1073.    {
  1074.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  1075.       return( FALSE );
  1076.    }
  1077.  
  1078.    return( SetStringArrayValue( name_of_value, strings_to_write ) );
  1079. }
  1080.  
  1081. BOOL CRegistry::SetValue( LPCTSTR name_of_value, const CString& string_to_write )
  1082. {
  1083.    ASSERT_VALID( this );
  1084.    ASSERT( name_of_value != NULL );
  1085.  
  1086.    if ( name_of_value == NULL )
  1087.    {
  1088.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  1089.       return( FALSE );
  1090.    }
  1091.  
  1092.    return( SetStringValue( name_of_value, string_to_write ) );
  1093. }
  1094.  
  1095. BOOL CRegistry::SetValue( LPCTSTR             name_of_value, 
  1096.                           const KeyValueTypes type_of_value_to_set, 
  1097.                           const PBYTE         address_of_value_data, 
  1098.                           const DWORD         size_of_data )
  1099. {
  1100.    ASSERT_VALID( this );
  1101.    ASSERT( name_of_value         != NULL );
  1102.    ASSERT( address_of_value_data != NULL );
  1103.  
  1104.    if ( name_of_value == NULL || address_of_value_data == NULL )
  1105.    {
  1106.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  1107.       return( FALSE );
  1108.    }
  1109.  
  1110.    m_ErrorCode = ::RegSetValueEx( m_KeyHandle,
  1111.                                   name_of_value,
  1112.                                   0,
  1113.                                   type_of_value_to_set,
  1114.                                   address_of_value_data,
  1115.                                   size_of_data );
  1116.  
  1117.    if ( m_ErrorCode == ERROR_SUCCESS )
  1118.    {
  1119.       return( TRUE );
  1120.    }
  1121.    else
  1122.    {
  1123.       return( FALSE );
  1124.    }
  1125. }
  1126.  
  1127. BOOL CRegistry::UnLoad( LPCTSTR name_of_subkey_to_unload )
  1128. {
  1129.    ASSERT_VALID( this );
  1130.    ASSERT( name_of_subkey_to_unload != NULL );
  1131.  
  1132.    if ( name_of_subkey_to_unload == NULL )
  1133.    {
  1134.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  1135.       return( FALSE );
  1136.    }
  1137.  
  1138.    m_ErrorCode = ::RegUnLoadKey( m_KeyHandle, name_of_subkey_to_unload );
  1139.  
  1140.    if ( m_ErrorCode == ERROR_SUCCESS )
  1141.    {
  1142.       return( TRUE );
  1143.    }
  1144.    else
  1145.    {
  1146.       return( FALSE );
  1147.    }
  1148. }
  1149.